import { Component, OnInit } from '@angular/core'
import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms'
import { Observable } from 'rxjs'
import { map, take, concatMap, tap } from 'rxjs/operators'
import { NzMessageService } from 'ng-zorro-antd'

import { NewPageAccessor } from '@shared/components/new-page/new-page.interface'
import { I18NService } from '@core'
import { DepositDataService } from '../../deposit-data.service'
import { DepositService } from '../../deposit.service'
import { IDepositCollection } from '@shared/interfaces/deposit'
import { CurrencyService } from '@shared/services/currency.service'
import { numScale, makeAllControlDirty } from 'app/utils/helpers'

@Component({
  selector: 'app-deposit-new-return',
  templateUrl: './return-form.component.html',
  styleUrls: ['../../../../../shared/styles/new-page-form.less'],
})
export class DepositReturnFormComponent implements NewPageAccessor, OnInit {
  constructor(
    private fb: FormBuilder,
    private msg: NzMessageService,
    private i18n: I18NService,
    private depositService: DepositService,
    private dataService: DepositDataService,
    private currencyService: CurrencyService,
  ) {}

  data: any
  payload: IDepositCollection
  isLoading = true
  depositAmtPrecision = 0
  form: FormGroup = this.fb.group({})
  depositFormData: IDepositCollection
  totalAmt: number
  currency: string
  errorTips = {}
  rateMarks = {
    1: '1%',
    25: '25%',
    50: '50%',
    75: '75%',
    100: '100%',
  }
  isRateAvailable = false

  returnTypeByRate = 'byRate'
  returnTypeByAmt = 'byAmt'

  get depositAmtCtrl(): FormControl {
    return this.form.get('depositAmt') as FormControl
  }

  get returnTypeCtrl(): FormControl {
    return this.form.get('returnType') as FormControl
  }

  get rateCtrl(): FormControl {
    return this.form.get('rate') as FormControl
  }

  ngOnInit() {
    this.form = this.fb.group({
      returnType: ['', [Validators.required]],
      rate: [1, []],
      depositAmt: ['', []],
      remark: ['', [Validators.required, Validators.maxLength(50)]],
    })

    this.returnTypeCtrl.valueChanges.subscribe(value => {
      switch (value) {
        case this.returnTypeByRate:
          this.isRateAvailable = true
          this.depositAmtCtrl.disable()
          this.depositAmtCtrl.setValue('')
          this.rateCtrl.setValue(1)
          break
        case this.returnTypeByAmt:
          this.isRateAvailable = false
          this.depositAmtCtrl.enable()
          this.depositAmtCtrl.setValue('')
          this.rateCtrl.setValue(1)
          break
        default:
          break
      }
    })

    this.rateCtrl.valueChanges.subscribe(value => {
      const amt = Math.round((this.totalAmt * value) / 100)
      this.amtScale(this.currency, amt).subscribe(parsedAmt => this.depositAmtCtrl.setValue(parsedAmt))
    })

    this.dataService.depositData$.value$
      .pipe(
        concatMap(data => {
          this.depositFormData = data
          return this.depositService.getDepositAmtOfStore(data.intStoreCode)
        }),
        take(1),
      )
      .subscribe(storeDeposit => {
        this.totalAmt = storeDeposit.depositAmt
        this.currency = storeDeposit.depositCurr

        // populate default value
        if (this.depositFormData.singlePercent) {
          this.returnTypeCtrl.setValue(this.returnTypeByRate)
        } else {
          this.returnTypeCtrl.setValue(this.returnTypeByAmt)
        }
        this.rateCtrl.setValue(this.depositFormData.singlePercent)
        this.depositAmtCtrl.setValue(this.depositFormData.depositAmt)
        this.form.get('remark').setValue(this.depositFormData.remark)
        this.depositAmtCtrl.setValidators([
          Validators.required,
          Validators.min(1),
          Validators.max(storeDeposit.depositAmt),
        ])
        this.initErrorTips()
        this.isLoading = false
      })
  }

  checkValid(): boolean {
    if (this.form.valid) {
      this.pushDataToStore()
      this.msg.success(this.trans('GENERAL.NOTIFICATION.VALIDATION_SUCCESS'))
      return true
    }

    makeAllControlDirty(this.form)
    return false
  }

  pushDataToStore(): void {
    const data: IDepositCollection = {
      intStoreCode: this.depositFormData.intStoreCode,
      depositCurr: this.currency,
      depositAmt: this.depositAmtCtrl.value,
      singlePercent: this.rateCtrl.value,
      remark: this.form.get('remark').value,
      totalAmt: this.totalAmt,
    }

    this.payload = data
    this.dataService.setDepositData(Object.assign(this.depositFormData, data))
  }

  amtScale(currency: string, amt: number): Observable<number> {
    return this.currencyService.getDecimalByCode(currency).pipe(
      tap(digital => this.depositAmtPrecision = digital),
      map(digital => numScale(amt, -digital)),
    )
  }

  private trans(key: string, params?: Object): string {
    return this.i18n.fanyi(key, params)
  }

  private initErrorTips() {
    this.errorTips = {
      returnType: {
        required: this.trans('VALIDATION.REQUIRED_SELECT', { name: this.trans('xxxxx') }),
      },
      rate: {
        required: this.trans('VALIDATION.REQUIRED', { name: this.trans('xxxxx') }),
      },
      depositAmt: {
        required: this.trans('VALIDATION.REQUIRED', { name: this.trans('OPERATION.DEPOSIT.TARGET_AMT') }),
        min: this.trans('VALIDATION.MIN_VALUE', { value: '1' }),
        max: this.trans('VALIDATION.MAX_VALUE', { value: this.totalAmt }),
      },
      remark: {
        required: this.trans('VALIDATION.REQUIRED', { name: this.trans('GENERAL.INFO.REMARK') }),
        maxlength: this.trans('VALIDATION.MAX_LENGTH', { length: 50 }),
      },
    }
  }
}
